home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
001-025
/
scopedisk3
/
68kasm
/
src
/
a68kmain.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-18
|
20KB
|
641 lines
/*------------------------------------------------------------------*/
/* */
/* MC68000 Cross Assembler */
/* */
/* Copyright (c) 1985 by Brian R. Anderson */
/* */
/* Main program - March 20, 1988 */
/* */
/* This program may be copied for personal, non-commercial use */
/* only, provided that the above copyright notice is included */
/* on all copies of the source code. Copying for any other use */
/* without the consent of the author is prohibited. */
/* */
/*------------------------------------------------------------------*/
/* */
/* Originally published (in Modula-2) in */
/* Dr. Dobb's Journal, April, May, and June 1986. */
/* */
/* AmigaDOS conversion copyright (c) 1988 by Charlie Gibbs. */
/* */
/*------------------------------------------------------------------*/
char Version[] = "1.10 (March 20, 1988)";
#include <stdio.h>
#define PRIMARY
#include "a68kdef.h"
#include "a68kglb.h"
/********************************************************************/
/* */
/* NOTE: the following line, plus any additional references */
/* to _fmode, is inserted to make this program work under */
/* the MS-DOS version of Lattice C. It is not necessary */
/* for the Amiga version, but does no harm if left in. */
/* */
/********************************************************************/
int _fmode = 0; /* File mode - 0x8000 for binary */
/* Functions */
extern int LineParts(), GetField(), Instructions(), ObjDir();
extern int GetSize(), GetInstModeSize(), GetMultReg();
extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl();
extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue();
#ifdef AZTEC_C
extern char *lmalloc();
#else
extern char *malloc();
#endif
extern FILE *fopen();
main(argc,argv) int argc; char *argv[];
{
char ListFN[MAXFN], SrecFN[MAXFN], EquateFN[MAXFN]; /* File names */
int MakeEqu; /* Create an equate file */
FILE *EquFile; /* Equate file pointer */
int keepobj; /* Keep object file with errors */
int endfile; /* End-of-file flag */
long maxheap, maxheap2; /* Maximum heap sizes */
int cmderror, dummy;
long templong, templ1, templ2, templ3;
char tempchar[MAXLINE];
register struct SymTab *sym;
register int i, j;
cmderror = FALSE; /* Clear command-line error flag */
SourceFN[0] = '\0'; /* Don't have source name yet */
HeaderFN[0] = EquateFN[0] = '\0'; /* No header or equate files yet */
ListFN[0] = SrecFN[0] = '\0'; /* Indicate default file names */
InclList[0] = '\0'; /* Clear the include directory list */
IdntName[0] = '\0'; /* Clear program unit name */
LnMax = 60;
Quiet = 10; /* Show progress every 10 lines */
XrefList = DumpSym = GotEqur = MakeEqu = KeepTabs = keepobj = FALSE;
SuppList = TRUE; /* Default to no listing file */
maxheap = DEFHEAP; /* Primary heap size default */
maxheap2 = DEFHEAP2; /* Secondary heap size default */
DebugStart = 32767; DebugEnd = 0; /* Disable debug displays. */
printf ("68000 Assembler - version %s\n", Version);
printf ("Copyright (c) 1985 by Brian R. Anderson\n");
printf ("AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs.\n\n");
for (i = 1; i < argc; i++) { /* Analyze command line */
if (argv[i][0] != '-') {
if (SourceFN[0] == '\0')
strcpy (SourceFN, argv[i]); /* Source file name */
else if (SrecFN[0] == '\0')
strcpy (SrecFN, argv[i]); /* Object file name */
else if (ListFN[0] == '\0')
strcpy (ListFN, argv[i]); /* Listing file name */
else {
fprintf (stderr, "Too many file names.\n");
cmderror = TRUE;
}
} else {
switch (toupper(argv[i][1])) {
case 'D':
DumpSym = TRUE;
if (argv[i][2]) {
fprintf (stderr, "Invalid symbol table dump switch.\n");
cmderror = TRUE;
}
break;
case 'E': /* Equate file name */
MakeEqu = TRUE;
if (EquateFN[0]) {
fprintf (stderr,
"Equate file is declared more than once.\n");
cmderror = TRUE;
} else if (argv[i][2])
strcpy (EquateFN, &argv[i][2]);
break;
case 'H': /* Header file name */
if (HeaderFN[0]) {
fprintf (stderr,
"Header file is declared more than once.\n");
cmderror = TRUE;
} else if (argv[i][2]) {
strcpy (HeaderFN, &argv[i][2]);
} else {
fprintf (stderr, "Header file name is missing\n");
cmderror = TRUE;
}
break;
case 'K':
keepobj = TRUE;
if (argv[i][2]) {
fprintf (stderr, "Invalid object file keep switch.\n");
cmderror = TRUE;
}
break;
case 'I': /* Include directories */
if (argv[i][2]) {
if (InclList[0])
strcat (InclList, ","); /* Add to previous list */
strcat (InclList, &argv[i][2]);
} else {
fprintf (stderr, "Include directory list is missing.\n");
cmderror = TRUE;
}
break;
case 'L': /* Listing file name */
SuppList = FALSE; /* Produce a listing */
if (ListFN[0]) {
fprintf (stderr,
"List file is declared more than once.\n");
cmderror = TRUE;
} else if (argv[i][2])
strcpy (ListFN, &argv[i][2]);
break;
case 'O': /* Object file name */
if (SrecFN[0]) {
fprintf (stderr,
"Object file is declared more than once.\n");
cmderror = TRUE;
} else if (argv[i][2]) {
strcpy (SrecFN, &argv[i][2]);
} else {
fprintf (stderr, "Object file name is missing\n");
cmderror = TRUE;
}
break;
case 'P':
if ((LnMax = CalcValue(&argv[i][2], 0)) < 10) {
fprintf (stderr, "Invalid page depth.\n");
cmderror = TRUE;
}
break;
case 'Q':
Quiet = CalcValue(&argv[i][2], 0);
break;
case 'S':
SFormat = TRUE;
if (argv[i][2]) {
fprintf (stderr, "Invalid S-format switch.\n");
cmderror = TRUE;
}
break;
case 'T':
KeepTabs = TRUE;
if (argv[i][2]) {
fprintf (stderr, "Invalid tab switch.\n");
cmderror = TRUE;
}
break;
case 'W':
if (argv[i][2] != ',') {
GetField (argv[i], 2, tempchar);
maxheap = CalcValue(tempchar, 0);
if (maxheap < MAXLINE)
maxheap = MAXLINE; /* Minimum heap size */
maxheap &= ~3L; /* Long-word alignment */
}
for (j = 2; argv[i][j]; j++) {
if (argv[i][j] == ',') { /* Find secondary size */
maxheap2 = CalcValue(&argv[i][j+1], 0);
if (maxheap2 < MAXLINE) {
maxheap2 = MAXLINE;
}
maxheap2 &= ~3L;
break;
}
}
break;
case 'X':
XrefList = TRUE;
SuppList = FALSE; /* We must want a listing */
if (argv[i][2]) {
fprintf (stderr, "Invalid cross-reference switch.\n");
cmderror = TRUE;
}
break;
case 'Z':
DebugStart = 0;
DebugEnd = 32767;
if (argv[i][2] != ',') { /* Debug dump starts here. */
GetField (argv[i], 2, tempchar);
DebugStart = CalcValue(tempchar, 0);
}
for (j = 2; argv[i][j]; j++) {
if (argv[i][j] == ',') { /* Debug dump ends here. */
DebugEnd = CalcValue(&argv[i][j+1], 0);
if (DebugEnd == 0)
DebugEnd = 32767;
}
}
break;
default:
fprintf (stderr, "Unrecognized switch.\n");
cmderror = TRUE;
break;
}
}
}
if (SourceFN[0] == '\0') { /* Default list file name */
fprintf (stderr, "Source file name is missing.\n");
cmderror = TRUE;
}
if (EquateFN[0] == '\0') { /* Default equate file name */
strcpy (EquateFN, SourceFN);
i = strlen (EquateFN);
while (--i > 0) {
if (EquateFN[i] == '.') {
EquateFN[i] = '\0'; /* Chop off name extension */
break;
}
}
strcat (EquateFN, ".equ"); /* Equate file name extension */
}
if (ListFN[0] == '\0') { /* Default list file name */
strcpy (ListFN, SourceFN);
i = strlen (ListFN);
while (--i > 0) {
if (ListFN[i] == '.') {
ListFN[i] = '\0'; /* Chop off name extension */
break;
}
}
strcat (ListFN, ".lst"); /* List file name extension */
}
if (SrecFN[0] == '\0') { /* Default object file name */
strcpy (SrecFN, SourceFN);
i = strlen (SrecFN);
while (--i > 0) {
if (SrecFN[i] == '.') {
SrecFN[i] = '\0'; /* Chop off name extension */
break;
}
}
if (SFormat)
strcat (SrecFN, ".s"); /* S-format name extension */
else
strcat (SrecFN, ".o"); /* AmigaDOS format extension */
}
if (strcmp (SourceFN, EquateFN) == 0) {
fprintf (stderr, "Source and equate file names are the same.\n");
cmderror = TRUE;
}
if (strcmp (SourceFN, ListFN) == 0) {
fprintf (stderr, "Source and listing file names are the same.\n");
cmderror = TRUE;
}
if (strcmp (SourceFN, SrecFN) == 0) {
fprintf (stderr, "Source and object file names are the same.\n");
cmderror = TRUE;
}
if (strcmp (EquateFN, ListFN) == 0) {
fprintf (stderr, "Equate and listing file names are the same.\n");
cmderror = TRUE;
}
if (strcmp (EquateFN, SrecFN) == 0) {
fprintf (stderr, "Equate and object file names are the same.\n");
cmderror = TRUE;
}
if (strcmp (ListFN, SrecFN) == 0) {
fprintf (stderr, "Listing and object file names are the same.\n");
cmderror = TRUE;
}
/* Open Files. */
_fmode = 0x8000; /****** MS-DOS only ******/
if (!cmderror) {
if ((InFile = fopen (SourceFN, "r")) == NULL) {
fprintf (stderr, "Unable to open source file.\n");
cmderror = TRUE;
}
}
_fmode = 0; /****** MS-DOS only ******/
if (!cmderror && MakeEqu) {
if ((EquFile = fopen (EquateFN, "w")) == NULL) {
fprintf (stderr, "Unable to open equate file.\n");
cmderror = TRUE;
fclose (InFile); /* Close any opened files */
}
}
if (!cmderror && !SuppList) {
if ((List = fopen (ListFN, "w")) == NULL) {
fprintf (stderr, "Unable to open listing file.\n");
cmderror = TRUE;
fclose (InFile);
if (MakeEqu)
fclose (EquFile);
}
}
if (!SFormat) _fmode = 0x8000; /****** MS-DOS only ******/
if (!cmderror) {
if ((Srec = fopen (SrecFN, "w")) == NULL ) {
fprintf (stderr, "Unable to open object code file.\n");
cmderror = TRUE;
fclose (InFile);
if (MakeEqu)
fclose (EquFile);
if (!SuppList)
fclose (List);
}
}
if (cmderror) {
fprintf (stderr, "\n");
fprintf (stderr, "Usage: a68k <source file>\n");
fprintf (stderr, " [-e<equate file>]\n");
fprintf (stderr, " [-h<header file>]\n");
fprintf (stderr, " [-i<include dirlist>]\n");
fprintf (stderr, " [-l<listing file>]\n");
fprintf (stderr, " [-o<object file>]\n");
fprintf (stderr, " [-p<page depth>]\n");
fprintf (stderr, " [-q[<quiet interval>]]\n");
fprintf (stderr, " [-w[<heap size>][,<heap size>]]\n");
fprintf (stderr, " [-d] [-k] [-s] [-t] [-x]\n\n");
fprintf (stderr, "Command-line arguments can appear in any order.\n");
fprintf (stderr, "Heap size default (bytes): -w");
fprintf (stderr, "%ld,%ld\n", (long) DEFHEAP, (long) DEFHEAP2);
fprintf (stderr, "\n");
exit(20);
}
#ifdef AZTEC_C
Heap = lmalloc (maxheap);
#else
Heap = malloc ((unsigned) maxheap);
#endif
if (Heap == NULL) {
fprintf (stderr, "Unable to allocate primary heap!\n");
exit(20);
}
HeapLim = Heap; /* Heap limit (start out empty) */
LowHeap = (Heap + maxheap);
SymStart = (struct SymTab *) (LowHeap); /* Symbol table */
#ifdef AZTEC_C
Heap2 = lmalloc (maxheap2);
#else
Heap2 = malloc ((unsigned) maxheap2);
#endif
if (Heap2 == NULL) {
fprintf (stderr, "Unable to allocate secondary heap!\n");
free (Heap); /* Release primary heap space */
exit(20);
}
NextFNS = Heap2;
InF = (struct InFCtl *) (Heap2 + maxheap2);
LowInF = --InF;
InFNum = OuterMac = SkipNest = InF->Pos = InF->MCnt = 0;
InF->Line = 0;
InF->UPtr = 0;
InF->NPtr = NextFNS;
InF->NArg = -1;
strcpy (NextFNS, SourceFN);
NextFNS += strlen (SourceFN) + 1;
High2 = NextFNS;
Low2 = (char *) LowInF;
_fmode = 0x8000; /****** MS-DOS only ******/
printf ("Assembling %s\n\n", SourceFN);
/*-------------------------------------------------------------------
Begin Pass 1.
*/
fprintf (stderr, "PASS 1\n");
LineCount = LabLine = MacCount = ErrorCount = NumSyms = 0;
AddrCnt = SectStart = 0L; /* Assume ORG = 0 to start */
CurrHunk = NextHunk = 0L; /* Start in hunk zero */
HunkType = HunkNone; /* We're not in a hunk yet */
HunkFlags = SectLine = 0;
endfile = ListOff = MakeHunk = Pass2 = FALSE;
/* Define ".A68K" as a SET symbol with an absolute value of 1.
This allows programs to identify this assembler. */
ReadSymTab (".A68K");
AddSymTab (".A68K", 1L, (long) ABSHUNK, 0, 4);
while (!endfile && (strcmp (OpCode, "END") != 0)) {
PrevDir = Dir; /* Save previous directive */
endfile = LineParts (dummy); /* Get a statement */
Dir = ObjDir (Srec); /* Process directives */
GetObjectCode (dummy); /* Length if executable */
if ((HunkType == HunkNone) && (AddrAdv != 0)) {
DoSection ("", 0, "", 0, "", 0); /* Start unnamed CODE section */
MakeHunk = TRUE;
}
if ((Label[0] != '\0')
&& (Dir != Set) && (Dir != Equr) && (Dir != Reg)) {
if (!ReadSymTab (Label)) { /* Make a new entry */
AddSymTab (Label, AddrCnt, CurrHunk, LineCount, 0);
} else if ((Sym->Flags & 1) /* If dup., ignore */
|| (Sym->Defn == NODEF)) { /* else fill in */
Sym->Val = AddrCnt; /* Current loc. */
Sym->Hunk = CurrHunk; /* Hunk number */
Sym->Defn = LineCount; /* Statement number */
Sym->Flags &= ~1; /* Clear XREF flag */
}
if (Dir == Equ) {
Sym->Val = ObjSrc; /* Equated value */
Sym->Hunk = Src.Hunk; /* Hunk number */
}
}
AddrCnt += AddrAdv; /* Advance location counter */
}
/*----------------------------------------------------------------
Begin Pass 2.
*/
fprintf (stderr, "PASS 2\n");
InF = (struct InFCtl *) (Heap2 + maxheap2);
InF--;
InFNum = OuterMac = SkipNest = InF->Pos = InF->MCnt = 0;
InF->Line = 0;
InF->UPtr = 0;
InF->NPtr = Heap2;
InF->NArg = -1;
fclose (InFile); /* "Rewind" the source file */
InFile = fopen (SourceFN, "r");
NextFNS = Heap2 + strlen (SourceFN) + 1;
Pass2 = TRUE;
LineCount = LabLine = MacCount = ErrorCount = 0;
AddrCnt = CurrHunk = SectStart = EndAddr = 0L;
HunkType = HunkNone;
HunkFlags = SectLine = 0;
endfile = ListOff = MakeHunk = FALSE;
if ((Sym = SymStart) < (struct SymTab *) (Heap + maxheap)) {
while (Sym->Flags & 16) {
Sym->Val = 0L; /* Back to start of all sections */
Sym++;
}
}
TTLstring[0] = '\0'; /* Clear title string */
if ((templong = (HeapLim - Heap) & 3L) != 0)
HeapLim += 4 - templong;
HighHeap = HeapLim; /* High-water mark in heap */
RelStart = (struct RelTab *) HeapLim; /* Relocation table */
RefStart = (struct Ref *) SymStart; /* Cross-reference table */
/* Sign on messages for listing file */
LnCnt = 999;
PgCnt = 0;
TTLstring[0] = '\0';
if (!SuppList) {
CheckPage (List, FALSE); /* Print headings */
fprintf (List, "68000 Cross Assembler\n");
fprintf (List, "Copyright (c) 1985 by Brian R. Anderson\n\n");
fprintf (List, "AmigaDOS conversion copyright (c) 1987");
fprintf (List, " by Charlie Gibbs.\n");
fprintf (List, "Version %s\n\n", Version);
LnCnt += 6;
}
StartSrec (Srec, IdntName); /* Write object header record */
/* Process the second pass. */
OpCode[0] = '\0'; /* Kill "END" from pass 1! */
while (!endfile && (strcmp(OpCode,"END") != 0)) {
PrevDir = Dir; /* Save previous directive */
endfile = LineParts (dummy); /* Get a statement */
if (!endfile) {
Dir = ObjDir (Srec); /* Process directives */
GetObjectCode (dummy); /* Executable object code */
if (Label[0] != '\0') { /* If statement is labeled, */
ReadSymTab (Label); /* check for duplicate defn. */
if (Sym->Defn != LineCount) {
AddRef (LineCount); /* Got one - flag as reference */
if (Dir == Set) {
if ((Sym->Flags & 4) == 0)
Error (LabLoc, SymDup); /* Can't SET normal label */
} else {
Error (LabLoc, SymDup); /* Ordinary duplicate */
}
} else if (Dir == Set) {
AddRef (LineCount); /* Flag all SETs as references */
} else {
if (Sym->Val != AddrCnt)
if ((Dir != Equ) && (Dir != Equr) && (Dir != Reg))
Error (0, Phase); /* Assembler error */
}
}
if (!SuppList)
WriteListLine (List);
WriteSrecLine (Srec);
AddrCnt += AddrAdv; /* Advance locaton counter */
} else {
Error (0, EndErr); /* END statement is missing */
if (!SuppList)
WriteListLine (List);
}
}
/*---------------------------------------------------------------------
Clean up.
*/
if (HunkType != HunkNone)
Sect->Val = AddrCnt; /* End of the last section */
fclose (InFile); /* Finished with source file */
EndSdata (Srec, EndAddr); /* Write remaining data and end record */
fclose (Srec); /* Finished with object file */
if ((ErrorCount != 0) && (!keepobj))
unlink (SrecFN); /* Scratch it if there were errors */
if (XrefList)
WriteSymTab (List); /* List the symbol table */
/* Write all absolute symbols to an equate file if desired. */
if (MakeEqu) {
fprintf (EquFile, "* Equate file for %s\n", SourceFN);
fprintf (EquFile, "* Created by A68k version %s\n", Version);
for (i = 0, sym = SymStart; i < NumSyms; i++, sym++) {
if (((sym->Hunk & 0x00007FFFL) == ABSHUNK)
&& ((sym->Flags == 0) || (sym->Flags == 2))) {
fprintf (EquFile, "%s\tEQU\t$", sym->Nam);
LongPut (EquFile, sym->Val, 4);
fprintf (EquFile, "\n");
}
}
fclose (EquFile);
}
/* Display final error count. */
fprintf (stderr, " \nEnd of assembly - ");
if (!SuppList)
fprintf (List, "\n\nEnd of assembly - ");
if (ErrorCount == 0) {
fprintf (stderr, "no errors were found.\n");
if (!SuppList)
fprintf (List, "no errors were found.\n\n");
} else if (ErrorCount == 1) {
fprintf (stderr, "1 error was found.\n");
if (!SuppList)
fprintf (List, "1 error was found.\n\n");
} else {
fprintf (stderr, "%d errors were found.\n", ErrorCount);
if (!SuppList)
fprintf (List, "%d errors were found.\n\n", ErrorCount);
}
/* Display heap usage. */
templong = (long) (HighHeap - Heap);
if (LowHeap < (char *) RefStart)
templong += (long) (Heap + maxheap - LowHeap);
else
templong += (long) (Heap + maxheap - (char *) RefStart);
fprintf (stderr, "Heap usage (bytes): -w%ld", templong);
if (!SuppList)
fprintf (List, "Heap usage (bytes): -w%ld", templong);
templong = (long) (High2 - Heap2);
if (Low2 < (char *) LowInF)
templong += (long) (Heap2 + maxheap2 - Low2);
else
templong += (long) (Heap2 + maxheap2 - (char *) LowInF);
fprintf (stderr, ",%ld\n", templong);
if (!SuppList)
fprintf (List, ",%ld\n\n", templong);
/* Display the total size of all section types. */
templ1 = templ2 = templ3 = 0;
for (i=0, sym=SymStart; (i<NumSyms)&&(sym->Flags&0x10); i++, sym++) {
templong = (sym->Val + 3) & ~3L; /* Hunk size */
j = (sym->Hunk & 0x3FFF0000L) >> 16; /* Hunk type */
if (j == HunkCode) /* Accumulate sizes by type */
templ1 += templong;
else if (j == HunkData)
templ2 += templong;
else
templ3 += templong;
}
fprintf (stderr, "Total hunk sizes: %lx code, ", templ1);
fprintf (stderr, "%lx data, %lx BSS\n", templ2, templ3);
if (!SuppList) {
fprintf (List, "Total hunk sizes: %lx code, ", templ1);
fprintf (List, "%lx data, %lx BSS\n", templ2, templ3);
}
/* Clean up and exit. */
if (!SuppList) {
fprintf (List, "\f"); /* One last page eject */
fclose (List); /* Finished with listing file */
}
free (Heap); /* Release heap space */
free (Heap2);
exit (ErrorCount ? 10 : 0); /* All done */
}